package cn.ex.ymcc.service.impl;

import cn.ex.ymcc.doc.CourseDoc;
import cn.ex.ymcc.domain.*;
import cn.ex.ymcc.dto.CourseAddDto;
import cn.ex.ymcc.feign.ESCourseFeignClient;
import cn.ex.ymcc.feign.MediaFeignClient;
import cn.ex.ymcc.globalexception.GlobalException;
import cn.ex.ymcc.mapper.*;
import cn.ex.ymcc.mq.CourseMessageSender;
import cn.ex.ymcc.result.JSONResult;
import cn.ex.ymcc.service.*;
import cn.ex.ymcc.util.AssertUtil;
import cn.ex.ymcc.util.StrUtils;
import cn.ex.ymcc.vo.CourseDetailInfoVo;
import cn.ex.ymcc.vo.CourseItemVo;
import cn.ex.ymcc.vo.CourserOrderVo;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author aze
 * @since 2022-07-25
 */
@Slf4j
@Service
@Transactional
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements ICourseService {


    @Autowired
    private ITeacherService teacherService;
    @Autowired
    private ICourseDetailService courseDetailService;
    @Autowired
    private ICourseResourceService courseResourceService;
    @Autowired
    private ICourseMarketService courseMarketService;
    @Autowired
    private ICourseTeacherService courseTeacherService;
    @Autowired
    private ICourseTypeService courseTypeService;
    @Autowired
    private ICourseSummaryService courseSummaryService;

    @Autowired
    private ESCourseFeignClient esCourseFeignClient;

    @Autowired
    private CourseMessageSender courseMessageSender;

    @Autowired
    private ICourseChapterService courseChapterService;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private MediaFeignClient mediaFeignClient;



    /**
     *保存课程到数据库
     * @param dto
     */
    @Override
    @Transactional
    public void save(CourseAddDto dto) {
        Course course = dto.getCourse();
        CourseDetail courseDetail = dto.getCourseDetail();
        CourseMarket courseMarket = dto.getCourseMarket();
        CourseResource courseResource = dto.getCourseResource();
        List<Long> teacharIds = dto.getTeacharIds();

        //参数校验
        Course courseTmp = selectByName(course.getName());
        AssertUtil.isNull(courseTmp,"课程已被注册！！！");
        //保存数据
        course.setStatus(Course.STATUS_ONLINE);

        course.setLoginId(1L);
        course.setLoginUserName("yhptest1");
        List<Teacher> teachers = teacherService.selectBatchIds(teacharIds);
        // 整成stream
        String teacherName = teachers.stream().
                map(teacher -> teacher.getName()).
                collect(Collectors.joining(","));


       /* StringBuilder sb = new StringBuilder();
        teachers.forEach(teacher -> {
            sb.append(teacher.getName()).append(",");
        });*/
        course.setTeacherNames(teacherName);
        //新增课程
        insert(course);
        //* 保存课程详情===========================
        courseDetail.setId(course.getId());
        courseDetailService.insert(courseDetail);

        //* 保存课程销售===========================
        courseMarket.setId(course.getId());
        courseMarketService.insert(courseMarket);

        //* 保存课程讲师===========================
        teacharIds.forEach(id->{
            CourseTeacher courseTeacher = new CourseTeacher();
            courseTeacher.setCourseId(course.getId());
            courseTeacher.setTeacherId(id);
            courseTeacherService.insert(courseTeacher);
        });
        //* 保存课程资源===========================
        courseResource.setCourseId(course.getId());
        courseResourceService.insert(courseResource);

        //* 初始化课程统计===========================
        CourseSummary courseSummary = new CourseSummary();
        courseSummary.setId(course.getId());
        courseSummaryService.insert(courseSummary);

        //课程类型表中的课程数+1======================
        CourseType type = courseTypeService.selectById(course.getCourseTypeId());
        type.setTotalCount(type.getTotalCount() + 1);
        courseTypeService.updateById(type);
    }

    /**
     * 课程详情页
     * @param courseId
     * @return
     */
    @Override
    public CourseDetailInfoVo searchCourseDetail(Long courseId) {
        AssertUtil.isNotNull(courseId,"请求非法");
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"请求非法");
        boolean onLine = course.getStatus() == Course.STATUS_ONLINE;
        AssertUtil.isTrue(onLine,"请求非法");//课程没有上线

        CourseDetail courseDetail = courseDetailService.selectById(courseId);
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        Wrapper<CourseTeacher> wrapper = new EntityWrapper<>();
        wrapper.eq("course_id",courseId);
        List<CourseTeacher> courseTeachers = courseTeacherService.selectList(wrapper);
        List<Long> teacherIds = courseTeachers.stream().map(teacher -> teacher.getTeacherId()).collect(Collectors.toList());
        List<Teacher> teachers = teacherService.selectBatchIds(teacherIds);

        //查询章节
        Wrapper<CourseChapter> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("course_id",courseId);
        List<CourseChapter> chapters = courseChapterService.selectList(entityWrapper);
       /*
       为章节所添加所对应的视频
        */
        chapters.forEach(chapter->{
            JSONResult jsonResult = mediaFeignClient.selectByChapterId(chapter.getId());
            if(jsonResult.isSuccess() && jsonResult.getData() != null){
                List<MediaFile> fileList = JSONObject.parseArray(jsonResult.getData().toString(), MediaFile.class);
                //添加对应章节的所有视频
                chapter.getMediaFiles().addAll(fileList);
            }
        });
        CourseDetailInfoVo vo = new CourseDetailInfoVo();
        vo.setCourse(course);
        vo.setCourseChapters(chapters);
        vo.setCourseMarket(courseMarket);
        vo.setCourseSummary(courseSummary);
        vo.setCourseDetail(courseDetail);
        vo.setTeachers(teachers);
        return vo;
    }

    /**
     * 查询课程和订单表，
     * 封装为CourseItemVo
     * @param courseIds
     * @return
     */
    @Override
    public CourserOrderVo courserOrderVo(String courseIds) {
        //以逗号分割
        List<Long> ids = StrUtils.splitStr2LongArr(courseIds);
        //转为set集合去重
        Set<Long> coursesIds = ids.stream().collect(Collectors.toSet());
        //校验课程id是否重复
        boolean ok = ids.size() == coursesIds.size();
        AssertUtil.isTrue(ok,"请求非法！");
        //根据每个课程Id查询课程 + 销售表
        List<CourseItemVo> courseInfos = new ArrayList<>();
        BigDecimal totalAmount = new BigDecimal(0);
        for (Long id : coursesIds) {
            //封装数据
            Course course = selectById(id);
            AssertUtil.isNotNull(course,"请求非法！");
            //课程不能上线
            boolean online = course.getStatus() == Course.STATUS_ONLINE;
            AssertUtil.isTrue(online,"请求非法！！");
            CourseMarket courseMarket = courseMarketService.selectById(id);
            AssertUtil.isNotNull(courseMarket,"请求非法！");
            CourseItemVo courseItemVo = new CourseItemVo(course, courseMarket);
            courseInfos.add(courseItemVo);
            //计算下单课程的总金额
            totalAmount = totalAmount.add(courseMarket.getPrice());
        }
        //将封装好的List<CourseItemVo> + 总金额，封装成CourserOrderVo
        return new CourserOrderVo(courseInfos,totalAmount);
    }

    private Course selectByName(String name) {
        Wrapper<Course> tWrapper = new EntityWrapper<Course>();
        tWrapper.eq("name",name);
        return selectOne(tWrapper);
    }



    /**
     *课程上线，保存课程到es
     * @param courseId
     */
    @Override
    @Transactional
    public void onLineCourse(Long courseId) {
        //校验
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"课程为空！！");
        boolean offLine = course.getStatus() == Course.STATUS_OFFLINE;
        AssertUtil.isTrue(offLine,"课程状态不满足");
        //2.修改课程状态为上架，填写上架时间
        course.setStatus(Course.STATUS_ONLINE);
        course.setOnlineTime(new Date());
        updateById(course);


        CourseType type = courseTypeService.selectById(course.getCourseTypeId());
        CourseMarket courseMarket = courseMarketService.selectById(courseId);
        CourseSummary courseSummary = courseSummaryService.selectById(courseId);
        CourseDoc doc = new CourseDoc();
        //设置需要保存到Es的字段
        BeanUtils.copyProperties(course,doc);
        BeanUtils.copyProperties(courseMarket,doc);
        BeanUtils.copyProperties(courseSummary,doc);
        doc.setCourseTypeName(type.getName());//这里要单独赋值
        String chargeName = courseMarket.getCharge() == 1 ? "免费" : "收费";
        doc.setChargeName(chargeName);

        JSONResult result = esCourseFeignClient.onLineCourse(doc);
        AssertUtil.isTrue(result.isSuccess(),"课程发布失败");
        //课程发布成功了，推消息===========================
        try {
            courseMessageSender.sendMessage(course);
        } catch (GlobalException e) {
            e.printStackTrace();
            throw new GlobalException("课程消息推送失败");
        }catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 课程下线
     * @param courseId
     */
    @Override
    public void offLineCourse(Long courseId) {
        Course course = selectById(courseId);
        AssertUtil.isNotNull(course,"该课程为空");
        //判断课程状态
        boolean offLine = course.getStatus() == Course.STATUS_ONLINE;
        AssertUtil.isTrue(offLine,"课程状态不满足");
        //修改课程状态为下线
        course.setStatus(Course.STATUS_OFFLINE);
        updateById(course);
        //删除es
        JSONResult jsonResult = esCourseFeignClient.offLineCourse(course.getId());
        AssertUtil.isTrue(jsonResult.isSuccess(),"课程下线失败");
    }


}